export const metadata = {
  description: "Manage permissions of CoValues using Groups. Learn how to add members to a Group, check permissions, and more."
};

import { Alert, CodeGroup } from "@/components/forMdx";

# Groups as permission scopes

Every CoValue has an owner, which can be a `Group` or an `Account`.

You can use a `Group` to grant access to a CoValue to **multiple users**. These users can
have different roles, such as "writer", "reader" or "admin".

CoValues owned by an Account can only be accessed by that Account. Additional collaborators cannot be added,
and the ownership cannot be transferred to another Account. This makes account ownership very rigid.

Creating a Group for every new CoValue is a best practice, even if the Group only has a single user in it
(this is the default behavior when creating a CoValue with no explicit owner).

<Alert variant="info" className="flex gap-2 items-center my-4">
While creating CoValues with Accounts as owners is still technically possible for backwards compatibility,
it will be removed in a future release.
</Alert>

## Role Matrix
<table>
  <thead>
    <tr>
      <th>Role</th>
      <th>admin</th>
      <th>manager</th>
      <th>writer</th>
      <th>writeOnly</th>
      <th>reader</th>
    </tr>
  </thead>
  <tbody>
  <tr>
      <th>Summary</th>
      <td>Full control</td>
      <td>Delegated management</td>
      <td>Standard writer</td>
      <td>Blind submissions</td>
      <td>Viewer</td>
    </tr>
    <tr>
      <th>Can add admins<sup>*</sup></th>
      <td>✅</td>
      <td>❌</td>
      <td>❌</td>
      <td>❌</td>
      <td>❌</td>
    </tr>
    <tr>
      <th>Can add/remove managers</th>
      <td>✅</td>
      <td>❌</td>
      <td>❌</td>
      <td>❌</td>
      <td>❌</td>
    </tr>
    <tr>
      <th>Can add/remove readers and writers</th>
      <td>✅</td>
      <td>✅</td>
      <td>❌</td>
      <td>❌</td>
      <td>❌</td>
    </tr>
    <tr>
      <th>Can write</th>
      <td>✅</td>
      <td>✅</td>
      <td>✅</td>
      <td>✅<sup>**</sup></td>
      <td>❌</td>
    </tr>
    <tr>
      <th>Can read</th>
      <td>✅</td>
      <td>✅</td>
      <td>✅</td>
      <td>❌<sup>***</sup></td>
      <td>✅</td>
    </tr>
  </tbody>
</table>

<sup>*</sup> `admin` users cannot be removed by anyone else, they must leave the group themselves.

<sup>**</sup> `writeOnly` users can only create and edit their own updates/submissions.

<sup>***</sup> `writeOnly` cannot read updates from other users.

## Creating a Group

Here's how you can create a `Group`.

<CodeGroup>
```ts index.ts#Basic
```
</CodeGroup>

The `Group` itself is a CoValue, and whoever owns it is the initial admin.

You typically add members using [public sharing](/docs/permissions-and-sharing/sharing#public-sharing) or [invites](/docs/permissions-and-sharing/sharing#invites).
But if you already know their ID, you can add them directly (see below).

## Adding group members by ID

You can add group members by ID by using `co.account().load` and `Group.addMember`.

<CodeGroup>
```tsx index.ts#AddMember
```
</CodeGroup>

## Changing a member's role

To change a member's role, use the `addMember` method.

<CodeGroup>
```ts index.ts#ChangeRole
```
</CodeGroup>

Bob just went from a writer to a reader.

**Note:** only admins and managers can change a member's role.

## Removing a member

To remove a member, use the `removeMember` method.

<CodeGroup>
```ts index.ts#RemoveMember
```
</CodeGroup>

Rules:
- All roles can remove themselves
- Admins can remove all roles (except other admins)
- Managers can remove users with less privileged roles (writer, writeOnly, reader)

## Getting the Group of an existing CoValue

You can get the group of an existing CoValue by using `coValue.$jazz.owner`.

<CodeGroup>
```ts index.ts#GetGroup
```
</CodeGroup>

## Checking the permissions

You can check the permissions of an account on a CoValue by using the `canRead`, `canWrite`, `canManage` and `canAdmin` methods.

<CodeGroup>
```ts index.ts#CheckPermissions
```
</CodeGroup>

To check the permissions of another account, you need to load it first:

<CodeGroup>
```ts index.ts#CheckPermissionsAlice
```
</CodeGroup>
